package cn.coderliu.config;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisClusterManager;
import org.crazycake.shiro.RedisManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 *
 */
@Configuration
public class ShiroConfig {

    private static final String CACHE_KEY = "shiro:cache:";

    @Autowired
    RedisProperties redisProperties;

    @Bean
    public ShiroFilterFactoryBean shirFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);        //设置安全管理器
        //  shiroFilterFactoryBean.setLoginUrl("/login");// 	如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        //  shiroFilterFactoryBean.setSuccessUrl("/index"); //  登录成功后要跳转的链接
        //  shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");//未授权界面;
        Map<String, String> filterMap = new HashMap<>();

        filterMap.put("/user/login", "anon");
        filterMap.put("/logout", "logout");//配置退出 过滤器,其中的具体的退出代码Shiro已经实现
        filterMap.put("/**", "authc");//过滤链定义，从上向下顺序执行，一般将/**放在最为下边
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;

    }

    //权限管理，配置主要是Realm的管理认证
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager securityManager(RealmConfig realm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);        //设置realm.
        // 自定义缓存实现 使用redis
        return securityManager;
    }

    //将自己的验证方式加入容器
    //参数：@Qualifier("hashedCredentialsMatcher")HashedCredentialsMatcher hCM
    @Bean
    public RealmConfig myShiroRealm(HashedCredentialsMatcher hCM) {
        RealmConfig myShiroRealm = new RealmConfig();
        myShiroRealm.setCredentialsMatcher(hCM);
        return myShiroRealm;
    }

    //凭证匹配器（由于密码校验交给Shiro的SimpleAuthenticationInfo进行处理了）
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
        hashedCredentialsMatcher.setHashIterations(2);//散列的次数，比如散列两次，相当于 md5(md5(""));
        return hashedCredentialsMatcher;
    }


    /**
     * Redis集群使用RedisClusterManager，单个Redis使用RedisManager
     */
    @Bean
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(redisProperties.getHost() + ":" + redisProperties.getPort());
        redisManager.setPassword(redisProperties.getPassword());
        return redisManager;
    }

    @Bean
    public RedisCacheManager redisCacheManager(RedisManager redisManager) {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager);
        redisCacheManager.setExpire(86400);
        redisCacheManager.setKeyPrefix(CACHE_KEY);
        return redisCacheManager;
    }

}
